#include "wav.h"
#include <string.h>



using namespace std;


wav::wav(void)
{
    dataReadIndex = 0;
    memset(&wavInfo,0,sizeof(wavInfo));
    wavFile = new ifstream;

}

wav::~wav()
{
    wavFile->close();
    delete wavFile;
}

int wav::open(string filePath)
{
	unsigned int curPoint,ChunkID,ChunkSize,Format,SampleRate,ByteRate;
	unsigned short PCMFormat,NumChannels,BlockAlign,BitsPerSample;

    wavFile->open(filePath,ios::binary | ios::in);
    if(!wavFile)
    {
        fprintf(stderr,"open %s error\r\n",filePath.c_str());
        return -1;
    }

	wavFile->read(reinterpret_cast<char *>(&ChunkID),4) ;
	if ( ChunkID != 0x46464952 )
	{
        wavFile->close() ;
        fprintf(stderr,"%s chunkID error\r\n",filePath.c_str());
		return -1;
	}
	wavFile->read((char *)&ChunkSize,4) ;//ChunkSize应该等于文件总长度减8
	wavFile->read((char *)&Format,4) ;
	if ( Format != 0x45564157 )//"WAVE"
	{
        fprintf(stderr,"%s format error\r\n",filePath.c_str());
		return -1;
	}

	while(1)
	{
		wavFile->read((char *)&ChunkID,4) ;
		wavFile->read((char *)&ChunkSize,4) ;
        if(wavFile->eof())
		{
			break;
		}
        curPoint = wavFile->tellg();
		if ( ChunkID == 0x20746D66 )	//"fmt "
		{
			wavFile->read((char *)&PCMFormat,2) ;
			wavFile->read((char *)&NumChannels,2) ;
			wavFile->read((char *)&SampleRate,4) ;
			wavFile->read((char *)&ByteRate,4) ;
			wavFile->read((char *)&BlockAlign,2) ;
			wavFile->read((char *)&BitsPerSample,2) ;
            wavInfo.bits = BitsPerSample;
            wavInfo.rate = SampleRate;
            wavInfo.channel = NumChannels;
            wavFile->seekg(curPoint + ChunkSize);
		}
		else if ( ChunkID == 0x61746164 ) //data
		{
            wavInfo.pcmDataStart = curPoint;
            wavInfo.sampleSize = ChunkSize / BlockAlign ;
            wavInfo.byteSize = ChunkSize;
			break ;
		}
		else
		{
			wavFile->seekg(curPoint + ChunkSize);
		}
	}
    return 0;
}



unsigned int wav::readSamples(char *buffer,unsigned int samples)
{
    if(!wavFile)
    {
        return -1;
    }

    unsigned int bytes = samples * wavInfo.channel * (wavInfo.bits / 8);
    unsigned int canRead = wavInfo.byteSize - dataReadIndex;

    if(canRead < bytes)
    {
        bytes = canRead;
    }

    wavFile->seekg(wavInfo.pcmDataStart + dataReadIndex);
    wavFile->read(buffer,bytes);
    dataReadIndex += bytes;
    if(dataReadIndex > wavInfo.byteSize)
    {
        dataReadIndex = wavInfo.byteSize;
    }

    return bytes / (wavInfo.channel * (wavInfo.bits / 8));
}

unsigned int wav::getPCMByteSize(void)
{
    return wavInfo.sampleSize;
}

unsigned int wav::getRate(void)
{
    return wavInfo.rate;
}

unsigned short wav::getBits(void)
{
    return wavInfo.bits;
}

unsigned short wav::getChannel(void)
{
    return wavInfo.channel;
}
